package com.siyoumi.validator;

import com.siyoumi.component.XApp;
import com.siyoumi.config.SysConfig;
import com.siyoumi.exception.EnumSys;
import com.siyoumi.exception.XException;
import com.siyoumi.exception.XWebException;
import com.siyoumi.util.XJson;
import com.siyoumi.util.XLog;
import com.siyoumi.util.XReturn;
import com.siyoumi.util.XStr;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;

import javax.validation.ConstraintValidatorContext;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Slf4j
public class XValidator {
    /**
     * 获取验证结果
     *
     * @param result       验证结果
     * @param onlyFirstErr true：只输出第1个错误
     * @param thowEx       true：抛出异常(XException)
     */
    static public XReturn getResult(BindingResult result, Boolean onlyFirstErr, Boolean thowEx) {
        XReturn r = EnumSys.SYS_VAILD.getR();
        if (!result.hasErrors()) {
            //验证成功
            return XReturn.getR(0);
        }

        List<FieldError> errors = result.getFieldErrors();
        Map<String, String> mapErrors = new HashMap<>();
        for (FieldError error : errors) {
            mapErrors.put(error.getField(), error.getDefaultMessage());

            if (onlyFirstErr) { //只输出第1个
                r.setErrMsg(error.getDefaultMessage());
                break;
            }
        }
        r.setData("errors", mapErrors);
        if (thowEx) {
            throw new XException(r);
        }

        return r;
    }

    static public XReturn getResult(BindingResult result) {
        return getResult(result, false, true);
    }

    static public XReturn getResult(BindingResult result, Boolean onlyFirstErr) {
        return getResult(result, onlyFirstErr, true);
    }


    static public FieldError getErr(String field, String errmsg) {
        return new FieldError("customer", field, errmsg);
    }


    /**
     * 验证提示，添加变量显示
     *
     * @param context 验证上下文
     * @param kv      变量
     */
    static public void addValidatorMessageParame(ConstraintValidatorContext context, Map<String, String> kv) {
        String messageDef = context.getDefaultConstraintMessageTemplate();
        for (Map.Entry<String, String> entry : kv.entrySet()) {
            messageDef = messageDef.replace(entry.getKey(), entry.getValue());
        }

        context.disableDefaultConstraintViolation();
        context.buildConstraintViolationWithTemplate(messageDef)
                .addConstraintViolation();
    }

    static public void err(Integer errcode, String errmsg) {
        throw new XException(XReturn.getR(errcode, errmsg));
    }

    static public void err(XReturn r) {
        if (r.err()) {
            throw new XException(r, false);
        }
    }

    /**
     * 前端显示错误
     *
     * @param r
     */
    static public void errWeb(XReturn r) {
        if (r.err()) {
            throw new XWebException(r);
        }
    }

    static public void isDev() {
        if (!SysConfig.getIns().isDev()) {
            err(EnumSys.ERR_VAL.getR("非开发环境"));
        }
    }

    /**
     * 断言表达式为true
     *
     * @param expression
     * @param errmsg
     */
    static public void isTrue(boolean expression, String errmsg) {
        if (expression) {
            err(EnumSys.SYS.getR(errmsg));
        }
    }

    /**
     * 参数为null
     *
     * @param object
     * @param errmsg
     */
    public static void isNull(Object object, String errmsg) {
        if (null == object) {
            err(EnumSys.ERR_VAL.getR(errmsg));
        }
    }

    public static void isNull(Object object) {
        isNull(object, "[Validator failed] - the object argument must be null");
    }

    /**
     * 字符串为空
     *
     * @param s
     * @param errmsg
     */
    public static void isNullOrEmpty(String s, String errmsg) {
        if (XStr.isNullOrEmpty(s)) {
            err(EnumSys.MISS_VAL.getR(errmsg));
        }
    }

    public static void isNullOrEmpty(String s) {
        isNullOrEmpty(s, "[Validator failed] - this argument is required; it must not be null or empty");
    }

    /**
     * 检查是否开事务
     */
    public static void checkTransaction() {
        if (!XApp.isTransaction()) {
            XValidator.err(EnumSys.SYS.getErrcode(), "请开事务");
        }
    }
}
